// src/stores/transportStore.js
import { defineStore } from 'pinia';
import apiClient from '@/api';
import { ElMessage } from 'element-plus';
import { useSettingsStore } from './settingsStore';

const UNFINISHED_TASKS_KEY = 's3-unfinished-tasks'

let taskIdCounter = 0;
let chunkIdCounter = 0;

export const useTransportStore = defineStore('transport', {
    state: () => ({
        transportList: [],
        isDrawerVisible: false,
    }),

    getters: {
        summary: (state) => {
            const total = state.transportList.length;
            // 【核心修正1】“上传中”现在只包括真正活动的任务
            const uploading = state.transportList.filter(t => ['上传中', '合并中...', '初始化...'].includes(t.status)).length;
            // 【核心修正2】新增一个“排队中”的独立计算
            const queuing = state.transportList.filter(t => t.status === '排队中').length;
            const success = state.transportList.filter(t => t.status === '成功').length;
            const failed = state.transportList.filter(t => ['失败', '已取消', '已中断'].includes(t.status)).length; // 失败也包括取消和中断

            // 【核心修正3】返回新的数据结构
            return { total, uploading, queuing, success, failed };
        }
    },

    actions: {
        addUploadTasks(tasks, bucketName, basePath, objectAcl = 'inherit', uploadMode = 'normal') {
            const newTasks = tasks.map(task => ({
                ...task, id: `task-${taskIdCounter++}`, status: '排队中',
                progress: 0, bucketName: bucketName, basePath: basePath, acl: objectAcl,
                uploadMode: uploadMode,
                multipart: uploadMode === 'multipart' ? { uploadId: null, chunks: null, completedParts: [], totalChunks: 0 } : null,
            }));
            this.transportList.push(...newTasks);
            this.isDrawerVisible = true;
            this.startProcessingQueue();
        },

        startProcessingQueue() {
            const settingsStore = useSettingsStore();
            const CONCURRENT_TASKS = settingsStore.concurrentTasks;
            const uploadingCount = this.transportList.filter(t => ['上传中', '合并中...', '初始化...'].includes(t.status)).length;
            const availableSlots = CONCURRENT_TASKS - uploadingCount;
            if (availableSlots <= 0) return;
            const waitingTasks = this.transportList.filter(t => t.status === '排队中').slice(0, availableSlots);
            waitingTasks.forEach(task => {
                if (task.status !== '排队中') {
                    console.warn(`[Scheduler] 任务 ${task.name} 状态已变为 ${task.status}，跳过启动。`);
                    // 重新调用调度器，尝试填充这个被跳过的槽位
                    this.startProcessingQueue();
                    return;
                }
                task.status = task.uploadMode === 'multipart' ? '初始化...' : '上传中';
                this.uploadFile(task);
            });
        },

        async uploadFile(task) {
            if (['成功', '失败', '已取消', '已暂停', '已中断'].includes(task.status)) {
                console.log(`[Uploader] 任务 ${task.name} 状态为 ${task.status}，直接中止上传逻辑。`);
                // 关键：即使中止，也要调用一次调度器，以确保队列能继续处理下一个任务。
                this.startProcessingQueue();
                return;
            }
            // 【核心修正1】在一个集中的try...catch...finally块中管理任务生命周期
            try {
                if (task.uploadMode === 'multipart') {
                    await this.uploadFileMultipart(task);
                } else {
                    await this.uploadFileNormal(task);
                }
                // 如果上面没有抛出错误，那么任务就是成功的
                // uploadFileMultipart/Normal 内部已经设置了 '成功' 状态，这里无需重复

            } catch (err) {
                // 只有当任务没有被明确标记为“成功”或“取消”时，才将其视为失败
                if (task.status !== '成功' && task.status !== '已取消' && task.status !== '已暂停') {
                    task.status = '失败';
                    console.error(`任务 ${task.name} 最终因错误而失败:`, err);
                }

            } finally {
                // 【核心修正2】调度下一个任务的逻辑，只在这里调用一次
                // 确保它在当前任务（无论成功失败）的Promise链完全结束后才执行
                this.startProcessingQueue();
            }
        },

        async uploadFileNormal(task) {
            const controller = new AbortController();
            task.abortController = controller;
            const s3Key = `${task.basePath || ''}${task.relativePath}`.replace(/^\//, '');
            const formData = new FormData();
            formData.append('file', task.raw);
            formData.append('key', s3Key);
            formData.append('acl', task.acl);
            try {
                // 状态已在 startProcessingQueue 中设置
                await apiClient.post(`/api/v1/upload/buckets/${task.bucketName}`, formData, {
                    onUploadProgress: (progressEvent) => {
                        if (progressEvent.total) {
                            task.progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
                        }
                    },
                    signal: controller.signal,
                });
                task.status = '成功';
                task.progress = 100;
            } catch (err) {
                if (err.name === 'CanceledError' || err.name === 'AbortError') {
                    task.status = '已取消';
                } else {
                    task.status = '失败';
                    console.error(`普通上传文件 ${task.name} 失败:`, err);
                    ElMessage.error(`文件 ${task.name} 上传失败`);
                }
            } finally {
                delete task.abortController;
            }
        },

        _saveTasksToLocalStorage() {
            const tasksToSave = this.transportList
                .filter(t => t.uploadMode === 'multipart' && ['上传中', '已暂停', '初始化...'].includes(t.status))
                .map(t => ({ // 只保存必要信息，避免保存 File/Blob 对象
                    id: t.id,
                    name: t.name,
                    size: t.size,
                    relativePath: t.relativePath,
                    bucketName: t.bucketName,
                    basePath: t.basePath,
                    acl: t.acl,
                    uploadMode: t.uploadMode,
                    multipart: {
                        uploadId: t.multipart.uploadId,
                        totalChunks: t.multipart.chunks.length,
                        completedParts: t.multipart.completedParts
                    }
                }));
            localStorage.setItem(UNFINISHED_TASKS_KEY, JSON.stringify(tasksToSave));
        },

        _removeTaskFromLocalStorage(taskId) {
            const tasks = JSON.parse(localStorage.getItem(UNFINISHED_TASKS_KEY) || '[]');
            const filteredTasks = tasks.filter(t => t.id !== taskId);
            localStorage.setItem(UNFINISHED_TASKS_KEY, JSON.stringify(filteredTasks));
        },

        async loadUnfinishedTasks() {
            const unfinished = JSON.parse(localStorage.getItem(UNFINISHED_TASKS_KEY) || '[]');
            if (unfinished.length === 0) return;

            const restoredTasks = unfinished.map(savedTask => ({
                ...savedTask,
                status: '已中断',
                progress: Math.round((savedTask.multipart.completedParts.length / savedTask.multipart.totalChunks) * 100),
                raw: null,
                // 【核心修正】恢复时，chunks数组保持为null，等待用户关联文件后再生成
                multipart: {
                    ...savedTask.multipart,
                    chunks: null,
                }
            }));

            this.transportList.push(...restoredTasks);

            ElMessage({ message: `已加载 ${unfinished.length} 个未完成的上传任务。`, type: 'info', duration: 5000 });
            // this.isDrawerVisible = true;
        },

        // 在 transportStore.js 的 actions 中

        pauseTask(taskId) {
            const task = this.transportList.find(t => t.id === taskId);
            if (!task || !['上传中', '初始化...', '排队中'].includes(task.status)) return;

            // 1. 立即更新主任务状态
            task.status = '已暂停';

            if (task.uploadMode === 'multipart') {
                // =============================================================
                // == 【核心修正】无条件地、原子化地更新所有分片的状态        ==
                // =============================================================
                if (task.multipart && task.multipart.chunks) {
                    // 1a. 中止所有正在飞行的请求
                    task.multipart.chunks.forEach(chunk => {
                        if (chunk.controller) {
                            chunk.controller.abort();
                        }
                    });

                    // 1b. 创建一个全新的chunks数组副本，并将所有非“成功”状态的分片都标记为“已暂停”
                    const newChunks = task.multipart.chunks.map(chunk => {
                        if (chunk.status !== '成功') {
                            return { ...chunk, status: '已暂停' };
                        }
                        return chunk; // 保持已成功分片的状态不变
                    });
                    task.multipart.chunks = newChunks;
                }
            } else { // 普通上传
                if (task.abortController) task.abortController.abort();
            }

            // 2. 持久化当前进度
            this._saveTasksToLocalStorage();

            // 3. 【新增】调用一次调度器，以防万一有其他任务可以启动
            this.startProcessingQueue();
        },

        // 在 transportStore.js 的 actions 中
        // 在 transportStore.js 的 actions 中

        resumeTask(taskId) {
            const task = this.transportList.find(t => t.id === taskId);
            if (!task || !['已暂停', '已中断'].includes(task.status)) return;

            if (!task.raw) {
                ElMessage.error(`无法继续任务 "${task.name}"，请在上传页面重新选择该文件进行匹配。`);
                return;
            }

            // =============================================================
            // == 【核心修正】在唤醒主任务的同时，唤醒所有未完成的分片      ==
            // =============================================================
            if (task.uploadMode === 'multipart' && task.multipart && task.multipart.chunks) {
                const newChunks = task.multipart.chunks.map(chunk => {
                    // 只“唤醒”那些之前被暂停或等待恢复的分片
                    if (['已暂停', '待恢复'].includes(chunk.status)) {
                        return { ...chunk, status: '排队中' };
                    }
                    return chunk; // 保持已成功或已失败分片的状态不变
                });
                task.multipart.chunks = newChunks;
            }

            // 将主任务放入队列
            task.status = '排队中';
            this.startProcessingQueue();
        },


        // src/stores/transportStore.js -> actions

        async uploadFileMultipart(task) {
            const settingsStore = useSettingsStore();
            const CHUNK_SIZE = settingsStore.defaultChunkSize * 1024 * 1024;
            const CONCURRENT_CHUNKS = settingsStore.concurrentChunks;
            const MAX_RETRIES = settingsStore.chunkMaxRetries;
            const RETRY_DELAY = settingsStore.chunkRetryDelay;
            const s3Key = `${task.basePath || ''}${task.relativePath}`.replace(/^\//, '');

            // 一个辅助函数，用于原子化地更新分片状态和进度
            const updateChunk = (chunkId, updates) => {
                const chunkIndex = task.multipart.chunks.findIndex(c => c.chunkId === chunkId);
                if (chunkIndex > -1) {
                    const newChunks = [...task.multipart.chunks];
                    newChunks[chunkIndex] = { ...newChunks[chunkIndex], ...updates };
                    task.multipart.chunks = newChunks;
                }
            };

            try {
                // 1. 初始化和切片 (逻辑不变)
                if (!task.multipart.uploadId) {
                    const totalChunks = Math.ceil(task.raw.size / CHUNK_SIZE);
                    task.multipart.totalChunks = totalChunks;

                    const chunks = [];
                    for (let i = 0; i < totalChunks; i++) {
                        const start = i * CHUNK_SIZE;
                        const end = Math.min(start + CHUNK_SIZE, task.raw.size);
                        chunks.push({
                            chunkId: `chunk-${chunkIdCounter++}`,
                            partNumber: i + 1, blob: task.raw.slice(start, end),
                            progress: 0, status: '排队中', controller: null,
                        });
                    }
                    task.multipart.chunks = chunks;

                    const initiateResponse = await apiClient.post(`/api/v1/buckets/${task.bucketName}/multipart/initiate`, { key: s3Key, acl: task.acl });
                    task.multipart.uploadId = initiateResponse.data.uploadId;
                    if (!task.multipart.uploadId) throw new Error("未能获取UploadId");
                    this._saveTasksToLocalStorage();
                }

                task.status = '上传中';
                const totalChunks = task.multipart.totalChunks;
                const completedPartNumbers = new Set(task.multipart.completedParts.map(p => p.PartNumber));
                const chunksToUpload = task.multipart.chunks.filter(c => !completedPartNumbers.has(c.partNumber));

                // ======================================================================
                // ==                 【核心重构部分】                                   ==
                // ======================================================================
                const uploadChunk = async (chunk) => {
                    if (['已取消', '已暂停'].includes(task.status)) {
                        updateChunk(chunk.chunkId, { status: task.status });
                        return;
                    }
                    chunk.controller = new AbortController();

                    const attemptUpload = async () => {
                        updateChunk(chunk.chunkId, { status: '上传中', progress: 0 }); // 重置进度
                        const formData = new FormData();
                        formData.append('key', s3Key);
                        formData.append('uploadId', task.multipart.uploadId);
                        formData.append('partNumber', chunk.partNumber);
                        formData.append('chunk', chunk.blob);

                        return apiClient.post(
                            `/api/v1/buckets/${task.bucketName}/multipart/upload-part`, formData, {
                            onUploadProgress: (progressEvent) => {
                                if (['已取消', '已暂停'].includes(task.status)) return;
                                const percent = progressEvent.total ? Math.round((progressEvent.loaded * 100) / progressEvent.total) : 0;
                                const currentChunk = task.multipart.chunks.find(c => c.chunkId === chunk.chunkId);
                                if (currentChunk && currentChunk.status === '上传中' && percent > currentChunk.progress) {
                                    updateChunk(chunk.chunkId, { progress: percent });
                                }
                            },
                            signal: chunk.controller.signal,
                        }
                        );
                    };

                    for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
                        try {
                            const response = await attemptUpload();
                            updateChunk(chunk.chunkId, { status: '成功', progress: 100 });

                            const completedSet = new Set(task.multipart.completedParts.map(p => p.PartNumber));
                            if (!completedSet.has(chunk.partNumber)) {
                                task.multipart.completedParts.push({ PartNumber: chunk.partNumber, ETag: response.data.etag });
                            }
                            task.progress = Math.round((task.multipart.completedParts.length / totalChunks) * 100);
                            this._saveTasksToLocalStorage();
                            return;

                        } catch (err) {
                            if (err.name === 'CanceledError' || ['已取消', '已暂停'].includes(task.status)) {
                                updateChunk(chunk.chunkId, { status: task.status });
                                throw err;
                            }
                            console.warn(`分片 ${chunk.partNumber} 第 ${attempt + 1} 次尝试失败:`, err);

                            if (attempt < MAX_RETRIES) {
                                updateChunk(chunk.chunkId, { status: `重试中(${attempt + 1}/${MAX_RETRIES})...` });
                                const delay = RETRY_DELAY * Math.pow(2, attempt);
                                await new Promise(resolve => setTimeout(resolve, delay));
                                if (['已取消', '已暂停'].includes(task.status)) {
                                    updateChunk(chunk.chunkId, { status: task.status });
                                    throw new Error("Retry aborted after delay.");
                                }
                            } else {
                                updateChunk(chunk.chunkId, { status: '失败' });
                                console.error(`分片 ${chunk.partNumber} 已达到最大重试次数，上传失败。`);
                                throw err;
                            }
                        }
                    }
                };
                // ======================================================================

                // 3. 并发调度器 (逻辑不变)
                const queue = [...chunksToUpload];
                const activeUploads = new Set();
                let firstError = null;
                await new Promise((resolve, reject) => {
                    const run = () => {
                        if (firstError || ['已取消', '已暂停'].includes(task.status)) {
                            if (activeUploads.size === 0) { firstError ? reject(firstError) : resolve(); }
                            return;
                        }
                        if (queue.length === 0 && activeUploads.size === 0) {
                            resolve();
                            return;
                        }
                        while (activeUploads.size < CONCURRENT_CHUNKS && queue.length > 0) {
                            const chunkToUpload = queue.shift();
                            const promise = uploadChunk(chunkToUpload)
                                .catch(err => { if (!firstError) firstError = err; })
                                .finally(() => {
                                    activeUploads.delete(promise);
                                    run();
                                });
                            activeUploads.add(promise);
                        }
                    };
                    run();
                });
                if (firstError) throw firstError;

                // 4. 合并分片 (逻辑不变)
                if (['已取消', '已暂停'].includes(task.status)) return;
                if (task.multipart.completedParts.length !== totalChunks) {
                    throw new Error("部分分片上传失败，任务已中断。");
                }
                task.status = '合并中...';
                task.multipart.completedParts.sort((a, b) => a.PartNumber - b.PartNumber);
                await apiClient.post(`/api/v1/buckets/${task.bucketName}/multipart/complete`, {
                    key: s3Key, uploadId: task.multipart.uploadId, parts: task.multipart.completedParts,
                });
                task.status = '成功';
                task.progress = 100;
                this._removeTaskFromLocalStorage(task.id);

            } catch (err) {
                // 5. 最终错误处理 (逻辑不变)
                if (err.name === 'CanceledError' || task.status === '已取消' || task.status === '已暂停') {
                    console.log(`分片上传任务 ${task.name} 已被中止。`);
                } else {
                    task.status = '失败';
                    console.error(`分片上传文件 ${task.name} 失败:`, err);
                    ElMessage.error(`文件 ${task.name} 分片上传失败`);
                    if (task.multipart?.uploadId) {
                        await this.abortMultipartUpload(task);
                    }
                }
            }
        },

        async abortMultipartUpload(task) {
            if (!task.multipart?.uploadId) return;
            try {
                await apiClient.post(`/api/v1/buckets/${task.bucketName}/multipart/abort`, {
                    key: `${task.basePath || ''}${task.relativePath}`.replace(/^\//, ''),
                    uploadId: task.multipart.uploadId,
                });
                console.log(`成功中止并清理了任务 ${task.name} 的碎片。`);
            } catch (abortErr) {
                console.error(`中止任务 ${task.name} 的碎片时失败:`, abortErr);
            }
        },

        // 在 transportStore.js 的 actions 中
        async cancelTask(taskId) {
            const task = this.transportList.find(t => t.id === taskId);
            if (!task) return;

            const originalStatus = task.status;
            // 1. 立即更新主任务状态
            task.status = '已取消';

            if (task.uploadMode === 'multipart') {
                // 2. 【核心修正】无条件地、原子化地更新所有分片的UI状态
                if (task.multipart && task.multipart.chunks) {
                    const newChunks = task.multipart.chunks.map(chunk => ({
                        ...chunk,
                        status: '已取消',
                        // (可选) 将进度条归零，视觉上更清晰
                        // progress: 0 
                    }));
                    task.multipart.chunks = newChunks;
                }

                // 3. 中止正在飞行的网络请求（如果任务之前是活动状态）
                if (originalStatus !== '已暂停' && originalStatus !== '已中断' && task.multipart && task.multipart.chunks) {
                    task.multipart.chunks.forEach(chunk => {
                        if (chunk.controller) chunk.controller.abort();
                    });
                }

                // 4. 通知后端清理碎片 (只要有uploadId就执行)
                if (task.multipart.uploadId) {
                    await this.abortMultipartUpload(task);
                }

            } else { // 普通上传
                if (task.abortController) task.abortController.abort();
            }

            // 5. 从localStorage中移除并触发下一次调度 (逻辑不变)
            this._removeTaskFromLocalStorage(task.id);
            this.startProcessingQueue();
        },

        removeTask(taskId) {
            this.transportList = this.transportList.filter(t => t.id !== taskId);
            this._removeTaskFromLocalStorage(taskId);
        },

        showDrawer() { this.isDrawerVisible = true; },
        hideDrawer() { this.isDrawerVisible = false; },
        clearCompleted() {
            this.transportList = this.transportList.filter(t => !['成功', '失败', '已取消'].includes(t.status));
        },

        // 在 transportStore.js 的 actions 中
        async pollUrlTaskStatus(task) {
            const intervalId = setInterval(async () => {
                const currentTask = this.transportList.find(t => t.id === task.id);
                if (!currentTask || ['成功', '失败', '已取消'].includes(currentTask.status)) {
                    clearInterval(intervalId);
                    return;
                }

                try {
                    // 【关键】这里的 API 应该是您之前用来检查文件是否存在的接口
                    // 我假设它是 /objects/exists，请根据您的实际情况调整
                    const fullKey = task.relativePath || `${task.basePath}${task.name}`;
                    // 注意：您需要确保有一个这样的后端接口
                    await apiClient.get(`/api/v1/buckets/${task.bucketName}/objects/details?key=${encodeURIComponent(fullKey)}`);

                    const taskOnSuccess = this.transportList.find(t => t.id === task.id);
                    if (taskOnSuccess) {
                        taskOnSuccess.status = '成功';
                        taskOnSuccess.progress = 100;
                    }
                    clearInterval(intervalId);

                } catch (error) {
                    if (error.response && error.response.status === 404) {
                        // 404 Not Found, 正常等待下一次
                    } else {
                        // 其他错误
                        const taskOnFailure = this.transportList.find(t => t.id === task.id);
                        if (taskOnFailure) {
                            taskOnFailure.status = '失败';
                        }
                        clearInterval(intervalId);
                    }
                }
            }, 5000);

            task.pollIntervalId = intervalId;
        },

        // 在 transportStore.js 的 actions 中
        addUrlTransferTask(taskInfoFromBackend) {
            const newTask = {
                ...taskInfoFromBackend,
                id: taskInfoFromBackend.id,
                uploadMode: 'url_transfer',
                status: '后台传输中',
                progress: 0,
                // 【核心修正】直接使用后端传来的 isLiveStream 标志
                isLiveStream: taskInfoFromBackend.isLiveStream || false,
            };

            this.transportList.push(newTask);
            this.isDrawerVisible = true;

            if (newTask.isLiveStream) {
                this.pollLiveStreamStatus(newTask);
            } else {
                this.pollHttpTaskCompletion(newTask);
            }
        },

        async stopLiveStreamTask(taskId) {
            const task = this.transportList.find(t => t.taskId === taskId);
            if (!task) {
                ElMessage.error("在列表中找不到要停止的任务");
                return;
            }

            try {
                // 1. 立即更新UI状态，给用户即时反馈
                task.status = '正在停止...';

                // 2. 调用后端的 stop API
                const response = await apiClient.post(`/api/v1/tasks/${taskId}/stop`);

                ElMessage.success(response.data.message || '停止信号已发送');

                // 后端会处理进程的终止和文件的合并。
                // 任务的状态会停留在“正在停止...”，直到下一次刷新或用户手动清除。
                // 这是一个合理的行为，因为任务确实已经结束了。

            } catch (error) {
                // 如果API调用失败，将状态改回，让用户可以重试
                const errorMessage = error.response?.data?.error || '发送停止信号失败';
                ElMessage.error(errorMessage);

                // =========================================================
                // ==                 【核心 Bug 修复】                   ==
                // =========================================================
                // 检查后端返回的错误信息是否是“任务不存在”
                if (errorMessage.includes('不存在') || errorMessage.includes('not found')) {
                    // 如果是，说明这个任务在后端已经没了，前端应该同步这个状态
                    task.status = '失败'; // 或者直接调用 removeTask(task.id)
                } else {
                    // 如果是其他错误（比如网络不通），才把状态恢复回去，让用户可以重试
                    task.status = '后台传输中';
                }
            }
        },

        pollLiveStreamStatus(task) {
            // 【关键】将任务的 id 和 taskId 在闭包中保存起来
            const targetTaskId = task.taskId;
            const targetId = task.id;

            const intervalId = setInterval(async () => {
                // 1. 【核心修正】直接使用闭包中保存的 targetId 来查找任务
                const currentTask = this.transportList.find(t => t.id === targetId);

                // 2. 检查这个【特定的】任务是否还需要轮询
                if (!currentTask || !['后台传输中', '正在停止...'].includes(currentTask.status)) {
                    clearInterval(intervalId);
                    return;
                }

                try {
                    // 3. 使用闭包中保存的 targetTaskId 发起请求
                    await apiClient.get(`/api/v1/tasks/${targetTaskId}/status`);
                } catch (error) {
                    if (error.response && error.response.status === 404) {
                        clearInterval(intervalId);

                        // 4. 【核心修正】只操作我们当前监控的这一个任务
                        const taskOnEnd = this.transportList.find(t => t.id === targetId);
                        if (!taskOnEnd) return;

                        if (taskOnEnd.status === '后台传输中') {
                            taskOnEnd.status = '失败';
                            ElMessage.error(`RTSP任务 "${taskOnEnd.name}" 在后端意外中断。`);
                        } else if (taskOnEnd.status === '正在停止...') {
                            taskOnEnd.status = '成功';
                            ElMessage.success(`RTSP任务 "${taskOnEnd.name}" 已成功停止。`);
                        }
                    }
                }
            }, 5000);

            // 将 intervalId 存入任务，这部分逻辑保持不变
            const taskInList = this.transportList.find(t => t.id === targetId);
            if (taskInList) {
                taskInList.pollIntervalId = intervalId;
            }
        },

        pollHttpTaskCompletion(task) {
            const intervalId = setInterval(async () => {
                const currentTask = this.transportList.find(t => t.id === task.id);
                if (!currentTask || ['成功', '失败'].includes(currentTask.status)) {
                    clearInterval(intervalId);
                    return;
                }

                try {
                    // =========================================================
                    // ==             【核心修正：调用新接口】                ==
                    // =========================================================
                    // 不再请求 objects/details，而是请求 tasks/status
                    const response = await apiClient.get(`/api/v1/tasks/${task.taskId}/status`);
                    const { progress } = response.data;

                    // 用后端返回的真实进度更新前端
                    currentTask.progress = progress;

                } catch (error) {
                    if (error.response && error.response.status === 404) {
                        // 404 意味着后端任务已结束 (成功或失败)
                        clearInterval(intervalId);
                        const taskOnEnd = this.transportList.find(t => t.id === task.id);
                        if (taskOnEnd) {
                            // 乐观地认为它是成功的
                            taskOnEnd.status = '成功';
                            taskOnEnd.progress = 100;
                        }
                    } else {
                        // 其他网络错误
                        console.warn(`轮询HTTP任务 ${task.name} 失败`, error);
                    }
                }
            }, 2000); // 2秒轮询一次，进度条更平滑
        },


        // 在 transportStore.js 的 actions 中
        reviveTaskWithFile(file, bucketName, basePath) {
            const s3Key = `${basePath || ''}${file.relativePath || file.name}`.replace(/^\//, '');
            const taskToRevive = this.transportList.find(t =>
                t.status === '已中断' &&
                t.bucketName === bucketName &&
                `${t.basePath || ''}${t.relativePath}`.replace(/^\//, '') === s3Key &&
                t.size === file.size
            );

            if (taskToRevive) {
                // --- 核心修正：在这里，一次性、原子化地构建完整的、状态正确的chunks数组 ---
                taskToRevive.raw = file.raw;
                const settingsStore = useSettingsStore();
                const CHUNK_SIZE = settingsStore.defaultChunkSize * 1024 * 1024;

                const chunks = [];
                const completedPartNumbers = new Set(taskToRevive.multipart.completedParts.map(p => p.PartNumber));

                for (let i = 0; i < taskToRevive.multipart.totalChunks; i++) {
                    const partNumber = i + 1;
                    const isCompleted = completedPartNumbers.has(partNumber);
                    const start = i * CHUNK_SIZE;
                    const end = Math.min(start + CHUNK_SIZE, taskToRevive.raw.size);
                    chunks.push({
                        chunkId: `chunk-${chunkIdCounter++}`,
                        partNumber: partNumber,
                        blob: taskToRevive.raw.slice(start, end),
                        progress: isCompleted ? 100 : 0,
                        status: isCompleted ? '成功' : '排队中',
                        controller: null,
                    });
                }

                // 一次性赋值，触发Vue更新
                taskToRevive.multipart.chunks = chunks;
                // taskToRevive.status = '已暂停';
                this.resumeTask(taskToRevive.id);
                ElMessage.success({
                    message: `已匹配到未完成的任务: ${file.name}，并已自动开始续传。`,
                    duration: 5000
                });
                // ElMessage.success({ message: `已匹配到任务: ${file.name}。请在传输列表点击“继续”。`, duration: 5000 });
                this.isDrawerVisible = true;
                return true;
            }
            return false;
        },
        pauseAllTasks() {
            // 找到所有可以被暂停的任务
            const tasksToPause = this.transportList.filter(t => ['上传中', '初始化...', '排队中'].includes(t.status));
            if (tasksToPause.length === 0) {
                ElMessage.info('没有正在进行中的任务可以暂停。');
                return;
            }
            // 逐个调用单个的暂停逻辑
            tasksToPause.forEach(task => this.pauseTask(task.id));
            ElMessage.success(`${tasksToPause.length}个任务已全部暂停。`);
        },
        resumeAllTasks() {
            // 1. 找到所有可以被继续的任务
            const tasksToResume = this.transportList.filter(t =>
                ['已暂停', '已中断'].includes(t.status)
            );

            if (tasksToResume.length === 0) {
                ElMessage.info('没有可以继续的任务。');
                return;
            }

            // 2. 检查这些任务是否有关联的源文件 (对于已中断的任务)
            const tasksWithoutFile = tasksToResume.filter(t => t.status === '已中断' && !t.raw);
            if (tasksWithoutFile.length > 0) {
                ElMessage.warning({
                    message: `${tasksWithoutFile.length}个中断的任务需要重新关联文件才能继续。`,
                    duration: 5000
                });
            }

            // 3. 逐个调用单个的继续逻辑
            let resumedCount = 0;
            tasksToResume.forEach(task => {
                // resumeTask 内部已经有 !t.raw 的检查，但我们只对能继续的计数
                if (task.status === '已暂停' || (task.status === '已中断' && task.raw)) {
                    this.resumeTask(task.id);
                    resumedCount++;
                }
            });

            if (resumedCount > 0) {
                ElMessage.success(`${resumedCount}个任务已加入队列等待上传。`);
            }
        },
        async cancelAllTasks() {
            // 找到所有尚未终结的任务
            const tasksToCancel = this.transportList.filter(t => !['成功', '失败', '已取消'].includes(t.status));
            if (tasksToCancel.length === 0) {
                ElMessage.info('没有任务可以取消。');
                return;
            }
            // 使用 Promise.all 来并发地执行所有取消操作
            await Promise.all(tasksToCancel.map(task => this.cancelTask(task.id)));
            ElMessage.warning(`${tasksToCancel.length}个任务已全部取消。`);
        },

        // 【核心新增3】清除全部记录
        clearAllTasks() {
            if (this.transportList.length === 0) {
                ElMessage.info('传输列表已为空。');
                return;
            }
            this.transportList = []; // 直接清空数组
            // (可选) 也可以顺便清空localStorage
            localStorage.removeItem(UNFINISHED_TASKS_KEY);
            ElMessage.success('已清除所有传输记录。');
        },
    },
});